const { v4: uuidv4 } = require('uuid');

/**
 * 任务状态枚举
 */
const TaskStatus = {
  PENDING: 'pending',
  DOWNLOADING: 'downloading',
  COMPLETED: 'completed',
  FAILED: 'failed',
  CANCELLED: 'cancelled'
};

/**
 * 下载任务模型
 */
class Task {
  constructor(url, customFileName = null) {
    this.id = uuidv4();
    this.url = url;
    this.customFileName = customFileName;
    this.status = TaskStatus.PENDING;
    this.fileName = null;
    this.filePath = null;
    this.fileSize = 0;
    this.downloadedSize = 0;
    this.progress = 0;
    this.addedAt = new Date();
    this.startedAt = null;
    this.completedAt = null;
    this.error = null;
    this.retryCount = 0;
    this.maxRetries = 3;
  }

  /**
   * 更新任务状态
   * @param {string} status - 新状态
   * @param {Object} data - 附加数据
   */
  updateStatus(status, data = {}) {
    this.status = status;

    switch (status) {
      case TaskStatus.DOWNLOADING:
        this.startedAt = new Date();
        this.error = null;
        break;
      case TaskStatus.COMPLETED:
        this.completedAt = new Date();
        this.progress = 100;
        this.error = null;
        break;
      case TaskStatus.FAILED:
        this.completedAt = new Date();
        this.error = data.error || 'Unknown error';
        break;
      case TaskStatus.CANCELLED:
        this.completedAt = new Date();
        this.error = 'Task cancelled by user';
        break;
    }

    // 更新其他数据
    Object.assign(this, data);
  }

  /**
   * 更新下载进度
   * @param {number} downloadedSize - 已下载大小
   * @param {number} totalSize - 总大小
   * @param {number} progress - 进度百分比
   */
  updateProgress(downloadedSize, totalSize, progress) {
    this.downloadedSize = downloadedSize;
    this.fileSize = totalSize || this.fileSize;
    this.progress = progress;
  }

  /**
   * 检查是否可以重试
   * @returns {boolean}
   */
  canRetry() {
    return this.status === TaskStatus.FAILED && this.retryCount < this.maxRetries;
  }

  /**
   * 增加重试次数
   */
  incrementRetry() {
    this.retryCount += 1;
  }

  /**
   * 重置任务状态（用于重试）
   */
  reset() {
    this.status = TaskStatus.PENDING;
    this.downloadedSize = 0;
    this.progress = 0;
    this.startedAt = null;
    this.completedAt = null;
    this.error = null;
  }

  /**
   * 获取任务摘要信息
   * @returns {Object}
   */
  getSummary() {
    return {
      id: this.id,
      url: this.url,
      status: this.status,
      fileName: this.fileName,
      fileSize: this.fileSize,
      downloadedSize: this.downloadedSize,
      progress: this.progress,
      addedAt: this.addedAt,
      startedAt: this.startedAt,
      completedAt: this.completedAt,
      error: this.error,
      retryCount: this.retryCount,
      maxRetries: this.maxRetries
    };
  }

  /**
   * 获取详细信息
   * @returns {Object}
   */
  getDetails() {
    return {
      ...this.getSummary(),
      filePath: this.filePath,
      customFileName: this.customFileName
    };
  }

  /**
   * 序列化为JSON
   * @returns {Object}
   */
  toJSON() {
    return this.getDetails();
  }

  /**
   * 从JSON数据创建任务实例
   * @param {Object} data - JSON数据
   * @returns {Task}
   */
  static fromJSON(data) {
    const task = new Task(data.url, data.customFileName);

    // 恢复所有属性
    Object.assign(task, {
      id: data.id,
      status: data.status,
      fileName: data.fileName,
      filePath: data.filePath,
      fileSize: data.fileSize,
      downloadedSize: data.downloadedSize,
      progress: data.progress,
      addedAt: new Date(data.addedAt),
      startedAt: data.startedAt ? new Date(data.startedAt) : null,
      completedAt: data.completedAt ? new Date(data.completedAt) : null,
      error: data.error,
      retryCount: data.retryCount || 0,
      maxRetries: data.maxRetries || 3
    });

    return task;
  }
}

module.exports = {
  Task,
  TaskStatus
};
